/// ------------------------------------------------------------------------------------------------------------------------------------
///
/// MIT License
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// Copyright (c) 2023 ycz. All rights reserved.
///
/// Created by ycz on 2023/10/26.
///
/// @file  y_sys.c
///
/// @brief
///     y_sys 是一些系统属性和功能的抽象
///
/// ------------------------------------------------------------------------------------------------------------------------------------



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 头文件
/// ------------------------------------------------------------------------------------------------------------------------------------

#include "y_sys.h"

#include <string.h>
#include "y_sa.h"



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 全局变量
/// ------------------------------------------------------------------------------------------------------------------------------------

static SYS_CONFIG_st g_default_config = {
        .sw_ver   = {Y_LL_SW_MAJOR, Y_LL_SW_MINOR, Y_LL_SW_PATCH},  ///< 软件版本
        .hw_ver   = {0, 0, 0},                                      ///< 硬件版本
        .dev_type = Y_LL_DEV_TYPE,                                  ///< 默认设备类型
        .dev_num  = Y_LL_DEV_NUM,                                   ///< 默认设备编号
        .mac      = {0},                                            ///< mac 地址
        .sn       = {0},                                            ///< sn 序列号
};  ///< 默认全局系统信息
static SYS_CONFIG_st g_config;       ///< 全局变量
static uint8_t       g_mac_str[13];  ///< mac 字符串
static uint8_t       g_sn_str[21];   ///< sn 字符串



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 公有函数
/// ------------------------------------------------------------------------------------------------------------------------------------

/// @brief   打印 y_sys 版本信息
void y_sys_print_version() {
    YLOG_VERSION("y_sys", Y_SYS_MAJOR, Y_SYS_MINOR, Y_SYS_PATCH);
}

/// @brief   打印 软件 版本号
void y_sys_print_software_version() {
    YLOGI("SOFTWARE VERSION : V%d.%d.%d", g_default_config.sw_ver.major, g_default_config.sw_ver.minor, g_default_config.sw_ver.patch);
}

/// @brief   打印 硬件 版本号
void y_sys_print_hardware_version() {
    g_config.hw_ver = y_ll_get_hardware_version();
    YLOGI("HARDWARE VERSION : V%d.%d.%d", g_config.hw_ver.major, g_config.hw_ver.minor, g_config.hw_ver.patch);
}

/// @brief   打印系统配置信息
void y_sys_print_config() {
    YLOGI("SYS  software                     : V%d.%d.%d", g_config.sw_ver.major, g_config.sw_ver.minor, g_config.sw_ver.patch);
    YLOGI("SYS  hardware                     : V%d.%d.%d", g_config.hw_ver.major, g_config.hw_ver.minor, g_config.hw_ver.patch);
    YLOGI("SYS  dev_type                     : %d", g_config.dev_type);
    YLOGI("SYS  dev_num   (modbus addr)      : %d", g_config.dev_num);
    YLOGI("SYS  mac                          : %s", y_sys_get_mac_str());
    YLOGI("SYS  sn                           : %s", y_sys_get_sn_str());
}

/// @brief   获取系统信息
/// @return  系统信息结构体
SYS_CONFIG_st y_sys_get_config() {
    return g_config;
}

/// @brief   获取 软件 版本号
/// @return  软件 版本号
VERSION_st y_sys_get_software_version() {
    return g_config.sw_ver;
}

/// @brief   获取 硬件 版本号
/// @return  硬件 版本号
VERSION_st y_sys_get_hardware_version() {
    return g_config.hw_ver;
}

/// @brief   获取 设备类型
/// @return  设备类型
uint8_t y_sys_get_dev_type() {
    return g_config.dev_type;
}

/// @brief   获取 设备编号
/// @return  设备编号
uint16_t y_sys_get_dev_num() {
    return g_config.dev_num;
}

/// @brief   获取 mac 地址
/// @return  mac 地址
uint8_t *y_sys_get_mac() {
    return g_config.mac;
}

/// @brief   获取 MAC 地址字符串
/// @return  mac 地址字符串
uint8_t *y_sys_get_mac_str() {
    sprintf((char *) g_mac_str, MAC_FORMAT, MAC_TO_STR(g_config.mac));
    return g_mac_str;
}

/// @brief   获取 sn
/// @return  sn
uint8_t *y_sys_get_sn() {
    return g_config.sn;
}

/// @brief   获取 sn 字符串
/// @return  sn 字符串
uint8_t *y_sys_get_sn_str() {
    for (int i = 0; i < sizeof(g_config.sn); ++i) {
        sprintf((char *) &g_sn_str[i * 2], "%02X", g_config.sn[i]);
    }
    return g_sn_str;
}

/// @brief   设置 设备类型
/// @param   [in] dev_type                 设备类型
/// @retval  true                          成功
/// @retval  false                         失败
bool y_sys_set_dev_type(uint8_t dev_type) {
    YLOGA_FALSE(dev_type);  // 断言
    g_config.dev_type = dev_type;
    y_nvs_set((uint8_t *) "dev_type", &dev_type, sizeof(dev_type), false);                           // 设备类型 单独保存 并且恢复出厂设置时不清零
    return y_nvs_set((uint8_t *) "sys_config", (uint8_t *) &g_config, sizeof(SYS_CONFIG_st), true);  // 更新系统配置参数
}

/// @brief   设置 设备编号
/// @param   [in] num                      设备编号
/// @retval  true                          成功
/// @retval  false                         失败
bool y_sys_set_dev_num(uint16_t num) {
    g_config.dev_num = num;
    return y_nvs_set((uint8_t *) "sys_config", (uint8_t *) &g_config, sizeof(SYS_CONFIG_st), true);  // 更新系统配置参数
}

/// @brief   设置 sn
/// @param   [in] sn                       设备类型
/// @retval  true                          成功
/// @retval  false                         失败
bool y_sys_set_sn(uint8_t *sn) {
    YLOGA_FALSE(sn);  // 断言
    memcpy(g_config.sn, sn, sizeof(g_config.sn));
    y_nvs_set((uint8_t *) "sn", sn, sizeof(g_config.sn), false);                                     // sn 号单独保存 并且恢复出厂设置时不清零
    return y_nvs_set((uint8_t *) "sys_config", (uint8_t *) &g_config, sizeof(SYS_CONFIG_st), true);  // 更新系统配置参数
}

/// @brief   系统信息初始化
/// @retval  true                          成功
/// @retval  false                         失败
bool y_sys_init() {

    uint16_t size = 0;
    if (y_nvs_get((uint8_t *) "sys_config", (uint8_t *) &g_config, &size) == false || size != sizeof(g_config)
        || y_utils_cmp_version(y_sys_get_software_version(), g_default_config.sw_ver) != 0) {  // 从 nvs 读取失败 获取版本发送变化
        // 更新系统默认配置到全局变量
        memcpy(&g_config, &g_default_config, sizeof(g_config));
        g_config.hw_ver = y_ll_get_hardware_version();                       // 获取硬件版本号
        memcpy(g_config.mac, y_ll_get_mac(), sizeof(g_default_config.mac));  // 获取设备 mac
        y_nvs_get((uint8_t *) "sn", g_config.sn, &size);                     // 获取 sn
        y_nvs_get((uint8_t *) "dev_type", &g_config.dev_type, &size);        // 获取设备类型
        y_sys_print_config();                                                // 打印系统配置信息
        return y_nvs_set((uint8_t *) "sys_config", (uint8_t *) &g_config, sizeof(SYS_CONFIG_st), true);
    }

    y_sys_print_config();  // 打印系统信息
    return true;
}